package com.zhifei.system.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.zhifei.common.core.redis.RedisCache;
import com.zhifei.common.utils.DateUtils;
import com.zhifei.common.utils.DispatcherUtils;
import com.zhifei.common.utils.Result;
import com.zhifei.common.utils.StringUtils;
import com.zhifei.system.domain.OnesProjectEntity;
import com.zhifei.system.domain.OnesProjectMemberEntity;
import com.zhifei.system.service.OnesProjectManhoursService;
import com.zhifei.system.service.OnesProjectMemberService;
import com.zhifei.system.service.OnesProjectService;
import com.zhifei.system.service.OnesService;
import com.zhifei.system.util.ones.OnesAccessTokenResult;
import com.zhifei.system.util.ones.OnesProjectManhoursInterfaceVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
public class OnesServiceImpl implements OnesService {

    @Autowired
    private RedisCache redisCache;
    @Autowired
    private OnesProjectService onesProjectService;
    @Autowired
    private OnesProjectMemberService onesProjectMemberService;
    @Autowired
    private OnesProjectManhoursService onesProjectManhoursService;

    public static final int MAX_TIME_OUT = 1000 * 120;

    @Override
    public Result listProject() {
        JSONObject jsonObject = new JSONObject();
        String queryFilter = "{" +
                "  buckets(groupBy: $groupBy, orderBy: $orderBy, pagination: {limit: 100, after: \"\", preciseCount: true}) {" +
                "    key" +
                "    projects(limit: 5000, orderBy: $projectOrderBy, filterGroup: $projectFilterGroup) {" +
                "      key" +
                "      projectMembers {uuid name title email status} " +
                "    _PQgvd3Xr" +
                "    _PtC8Fmgy" +
                "    _VCrghpWS" +
                "    _3VFXJk9h" +
                "    _LBeQBbKY" +
                " {uuid value}" +
                "    _TL37pvJc" +
                "    _SKC47RUD" +
                " {uuid value}" +
                "    _Xn6FsiyN" +
                " {uuid value}" +
                "    sprintCount" +
                "    taskCount" +
                "    taskCountDone" +
                "    taskCountInProgress" +
                "    taskCountToDo" +
                "    memberCount" +
                "    estimatedHours" +
                "    progress" +
                "    remainingManhour" +
                "    totalManhour" +
                "    uuid" +
                "    name" +
                "    status " +
                "{uuid name category}" +
                "    isPin" +
                "    isSample" +
                "    isArchive" +
                "    statusCategory" +
                "    assign " +
                "{uuid name avatar}" +
                "    owner " +
                "{uuid name avatar}" +
                "    createTime" +
                "    planStartTime" +
                "    planEndTime" +
                "    type  }  " +
                "key  pageInfo " +
                "{count preciseCount totalCount startPos startCursor endPos endCursor hasNextPage unstable" +
                "    }" +
                "  }" +
                "}";
        jsonObject.put("query",queryFilter);
        JSONObject variablesJson = new JSONObject();
        JSONObject projectOrderByJson = new JSONObject();
        projectOrderByJson.put("isPin","DESC");
        projectOrderByJson.put("namePinyin","ASC");
        projectOrderByJson.put("createTime","DESC");
        variablesJson.put("projectOrderBy",projectOrderByJson);
        JSONArray projectFilterGroupArray = new JSONArray();
        JSONObject projectFilterGroupJson = new JSONObject();
        projectFilterGroupJson.put("visibleInProject_equal",true);
        projectFilterGroupJson.put("isArchive_equal",false);
        projectFilterGroupArray.add(projectFilterGroupJson);
        variablesJson.put("projectFilterGroup",projectFilterGroupArray);
        JSONObject groupByJson = new JSONObject();
        JSONObject projectsJson = new JSONObject();
        groupByJson.put("projects",projectsJson);
        variablesJson.put("groupBy",groupByJson);
        jsonObject.put("variables",variablesJson);
        String result = this.postRequest("https://pm.chengdu-zhifei.com/project/api/project/team/2gByUoXi/items/graphql?t=projects-group-list-for-project-view",jsonObject);
        JSONObject resultJson = JSONObject.parseObject(result);
        JSONObject dataJson = resultJson.getJSONObject("data");
        JSONArray bucketsJsonArray = dataJson.getJSONArray("buckets");
        if(bucketsJsonArray!=null && bucketsJsonArray.size()>0){
            JSONObject bucketsJson = (JSONObject) bucketsJsonArray.get(0);
            JSONArray projectsJsonArray = bucketsJson.getJSONArray("projects");
            this.saveProject(projectsJsonArray);
        }
        return Result.success(result);
    }

    public void saveProject(JSONArray projectsJsonArray){
        List<String> projectIdList = new ArrayList<>();
        for (int i = 0; i < projectsJsonArray.size(); i++) {
            JSONObject projectJson = (JSONObject) projectsJsonArray.get(i);
            String projectId = projectJson.getString("uuid");//项目id
            String projectCode = projectJson.getString("_PtC8Fmgy");//项目编码
            if(StringUtils.isNotEmpty(projectCode) && !"必填".equals(projectCode) && !"待定".equals(projectCode)){
                projectIdList.add(projectId);
            }
            String projectName = projectJson.getString("name");//项目名称
            String projectStatus = null;//项目状态
            JSONObject statusJson = projectJson.getJSONObject("status");
            if(statusJson!=null){
                projectStatus = statusJson.getString("name");
            }
            String projectType = null;//项目类型
            JSONObject typeJson = projectJson.getJSONObject("_SKC47RUD");
            if(typeJson!=null){
                projectType = typeJson.getString("value");
            }
            String projectStage = null;//项目阶段
            JSONObject stageJson = projectJson.getJSONObject("_LBeQBbKY");
            if(stageJson!=null){
                projectStage = stageJson.getString("value");
            }
            String projectProgress = projectJson.getString("_TL37pvJc");//项目进度
            String projectSponsor = projectJson.getString("_VCrghpWS");//项目发起人
            String projectLeader = null;//项目负责人
            JSONObject leaderJson = projectJson.getJSONObject("assign");
            if(leaderJson!=null){
                projectLeader = leaderJson.getString("name");
            }
            Date planStartDate = null;//计划开始日期
            String planStartDateStr = projectJson.getString("planStartTime");
            if(StringUtils.isNotEmpty(planStartDateStr)){
                planStartDate = new Date(DispatcherUtils.parseLong(planStartDateStr+"000"));
            }
            Date planEndDate = null;//计划结束日期
            String planEndDateStr = projectJson.getString("planEndTime");//计划结束日期
            if(StringUtils.isNotEmpty(planEndDateStr)){
                planEndDate = new Date(DispatcherUtils.parseLong(planEndDateStr+"000"));
            }
            String projectWork = projectJson.getString("_3VFXJk9h");//项目工时
            String projectNature = null;//项目性质
            JSONArray natureJsonArray = projectJson.getJSONArray("_Xn6FsiyN");
            if(natureJsonArray!=null && natureJsonArray.size()>0){
                StringBuilder stringBuilder = new StringBuilder();
                for (int j = 0; j < natureJsonArray.size(); j++) {
                    String natureValue = natureJsonArray.getJSONObject(j).getString("value");
                    stringBuilder.append(natureValue+"、");
                }
                projectNature = stringBuilder.substring(0,stringBuilder.length()-1);
            }
            OnesProjectEntity onesProjectEntity = new OnesProjectEntity();
            onesProjectEntity.setProjectId(projectId);
            onesProjectEntity.setProjectCode(projectCode);
            onesProjectEntity.setProjectName(projectName);
            onesProjectEntity.setProjectStatus(projectStatus);
            onesProjectEntity.setProjectType(projectType);
            onesProjectEntity.setProjectStage(projectStage);
            onesProjectEntity.setProjectProgress(projectProgress);
            onesProjectEntity.setProjectSponsor(projectSponsor);
            onesProjectEntity.setProjectLeader(projectLeader);
            onesProjectEntity.setPlanStartDate(planStartDate);
            onesProjectEntity.setPlanEndDate(planEndDate);
            onesProjectEntity.setProjectWork(projectWork);
            onesProjectEntity.setProjectNature(projectNature);
            OnesProjectEntity onesProjectDo = onesProjectService.lambdaQuery().eq(OnesProjectEntity::getProjectId,projectId).one();
            if(onesProjectDo!=null){
                BeanUtils.copyProperties(onesProjectEntity,onesProjectDo,"id");
                onesProjectService.updateById(onesProjectDo);//修改
            }else{
                onesProjectService.save(onesProjectEntity);//新增
            }
            //项目成员
            String projectMembers = projectJson.getString("projectMembers");
            onesProjectMemberService.saveProjectMember(projectId,projectMembers);
        }
        //项目工时
        this.saveProjectManhours(projectIdList);
    }

    public void saveProjectManhours(List<String> projectIdList){
        List<OnesProjectManhoursInterfaceVo> onesProjectManhoursInterfaceVoList = new ArrayList<>();
        JSONObject jsonObject = new JSONObject();
        SimpleDateFormat sdf = new SimpleDateFormat("MM");
        String format = sdf.format(new Date());
        int month = Integer.parseInt(format);
        String queryFilter = "{buckets(groupBy:{manhours:{owner:{}}}," +
                "filter:{" +
                "manhours:{project:{uuid_in:["+projectIdList.stream().map(s -> "\"" + s + "\"").collect(Collectors.joining(","))+"]}," +
                "startTime_range: {from: \""+DateUtils.getFirstDayOfMonth(month)+"\",to: \""+DateUtils.getLastDayOfMonth(month)+"\"}," +
                "type_in:[\"recorded\"]}})" +
                "{manhours{" +
                "uuid " +
                "hours " +
                "startTime " +
                "owner{uuid  name email title} " +
                "task{uuid  name} " +
                "project{uuid name _PtC8Fmgy}} " +
                "aggregateInt(sum:\"manhours.hours\")}}";
        jsonObject.put("query",queryFilter);
        JSONObject variablesJson = new JSONObject();
        JSONObject projectOrderByJson = new JSONObject();
        variablesJson.put("projectOrderBy",projectOrderByJson);
        JSONObject groupByJson = new JSONObject();
        variablesJson.put("groupBy",groupByJson);
        jsonObject.put("variables",variablesJson);
        String result = this.postRequest("https://pm.chengdu-zhifei.com/project/api/project/team/2gByUoXi/items/graphql",jsonObject);
        JSONObject resultJson = JSONObject.parseObject(result);
        JSONObject dataJson = resultJson.getJSONObject("data");
        JSONArray bucketsJsonArray = dataJson.getJSONArray("buckets");
        if(bucketsJsonArray!=null && bucketsJsonArray.size()>0){
            for (int i = 0; i < bucketsJsonArray.size(); i++) {
                JSONObject bucketsJson = (JSONObject) bucketsJsonArray.get(i);
                JSONArray manhoursJSONArray = bucketsJson.getJSONArray("manhours");
                for(int j = 0; j < manhoursJSONArray.size(); j++){
                    JSONObject manhoursJson = (JSONObject) manhoursJSONArray.get(j);//每个人的项目工时
                    JSONObject projectJson = manhoursJson.getJSONObject("project");
                    String projectId = projectJson.getString("uuid");//项目id
                    String projectCode = projectJson.getString("_PtC8Fmgy");//项目编码
                    JSONObject userJson = manhoursJson.getJSONObject("owner");
                    String userId = userJson.getString("uuid");//用户id
                    String userEmail = userJson.getString("email");//用户邮箱
                    String userName = userJson.getString("name");//用户姓名
                    String userPost = userJson.getString("title");//用户岗位
                    JSONObject taskJson = manhoursJson.getJSONObject("task");
                    String taskName = taskJson.getString("name");//任务名称
                    String manhoursId = manhoursJson.getString("uuid");//工时id
                    Long manhours = DispatcherUtils.parseLong(manhoursJson.getString("hours"));
                    Date startTime = new Date(DispatcherUtils.parseLong(manhoursJson.getString("startTime")+"000"));
                    OnesProjectManhoursInterfaceVo onesProjectManhoursInterfaceVo = new OnesProjectManhoursInterfaceVo();
                    onesProjectManhoursInterfaceVo.setManhoursId(manhoursId);
                    onesProjectManhoursInterfaceVo.setProjectId(projectId);
                    onesProjectManhoursInterfaceVo.setProjectCode(projectCode);
                    onesProjectManhoursInterfaceVo.setUserId(userId);
                    onesProjectManhoursInterfaceVo.setUserEmail(userEmail);
                    onesProjectManhoursInterfaceVo.setUserName(userName);
                    onesProjectManhoursInterfaceVo.setUserPost(userPost);
                    onesProjectManhoursInterfaceVo.setTaskName(taskName);
                    onesProjectManhoursInterfaceVo.setManhours(manhours);
                    onesProjectManhoursInterfaceVo.setStartTime(startTime);
                    onesProjectManhoursInterfaceVoList.add(onesProjectManhoursInterfaceVo);
                }
            }
        }
        onesProjectManhoursService.saveProjectManhours(onesProjectManhoursInterfaceVoList);
    }

    public OnesAccessTokenResult getToken(){
        // 获取redis中token
        OnesAccessTokenResult onesAccessTokenResult = redisCache.getCacheObject("ones_access_token");
        // 判断token是否有值
        if (onesAccessTokenResult==null) {
            HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
            httpRequestFactory.setConnectionRequestTimeout(MAX_TIME_OUT);
            httpRequestFactory.setConnectTimeout(MAX_TIME_OUT);
            httpRequestFactory.setReadTimeout(MAX_TIME_OUT);
            RestTemplate restTemplate = new RestTemplate();
            restTemplate.setRequestFactory(httpRequestFactory);

            //组装请求参数,可以封装成实体类或者用map或者JSONObject等
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("email", "shiwenxu@zhifei-group.com");
            jsonObject.put("password", "Swx121315");
            HttpHeaders httpHeaders = new HttpHeaders();
            httpHeaders.set("Content-Type","application/json; charset=UTF-8");
            HttpEntity httpEntity = new HttpEntity(jsonObject.toJSONString(), httpHeaders);
            ResponseEntity<String> exchange = restTemplate.exchange("https://pm.chengdu-zhifei.com/project/api/project/auth/login", HttpMethod.POST, httpEntity, String.class);
            String respone = exchange.getBody();
            JSONObject responeJson = JSONObject.parseObject(respone);
            JSONObject userJson = responeJson.getJSONObject("user");
            String uuid = userJson.getString("uuid");
            String token = userJson.getString("token");
            onesAccessTokenResult = new OnesAccessTokenResult();
            onesAccessTokenResult.setUuid(uuid);
            onesAccessTokenResult.setToken(token);
            redisCache.setCacheObject("ones_access_token", onesAccessTokenResult, 365, TimeUnit.DAYS);
        }
        return onesAccessTokenResult;
    }

    public String getRequest(String url,JSONObject paramJson){
        HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
        httpRequestFactory.setConnectionRequestTimeout(MAX_TIME_OUT);
        httpRequestFactory.setConnectTimeout(MAX_TIME_OUT);
        httpRequestFactory.setReadTimeout(MAX_TIME_OUT);
        RestTemplate restTemplate = new RestTemplate();
        restTemplate.setRequestFactory(httpRequestFactory);
        OnesAccessTokenResult onesAccessTokenResult = this.getToken();
        if(paramJson!=null){
            url = this.parseJsonToUrlParams(url,paramJson);
        }
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.set("Ones-User-Id",onesAccessTokenResult.getUuid());
        httpHeaders.set("Ones-Auth-Token",onesAccessTokenResult.getToken());
        httpHeaders.set("Referer","https://pm.chengdu-zhifei.com/project/");
        HttpEntity httpEntity = new HttpEntity(null, httpHeaders);
        ResponseEntity<String> exchange = restTemplate.exchange(url, HttpMethod.GET, httpEntity, String.class);
        String respone = exchange.getBody();
        return respone;
    }

    public String postRequest(String url,JSONObject paramJson){
        HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
        httpRequestFactory.setConnectionRequestTimeout(MAX_TIME_OUT);
        httpRequestFactory.setConnectTimeout(MAX_TIME_OUT);
        httpRequestFactory.setReadTimeout(MAX_TIME_OUT);
        RestTemplate restTemplate = new RestTemplate();
        restTemplate.setRequestFactory(httpRequestFactory);
        OnesAccessTokenResult onesAccessTokenResult = this.getToken();
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.set("Content-Type","application/json; charset=UTF-8");
        httpHeaders.set("Ones-User-Id",onesAccessTokenResult.getUuid());
        httpHeaders.set("Ones-Auth-Token",onesAccessTokenResult.getToken());
        httpHeaders.set("Referer","https://pm.chengdu-zhifei.com/project/");
        HttpEntity httpEntity = new HttpEntity(paramJson.toJSONString(), httpHeaders);
        ResponseEntity<String> exchange = restTemplate.exchange(url, HttpMethod.POST, httpEntity, String.class);
        String respone = exchange.getBody();
        return respone;
    }

    public String parseJsonToUrlParams(String url,JSONObject jsonObject) {
        try {
            Iterator it = jsonObject.keySet().iterator();
            String paramStr = "";
            while (it.hasNext()) {
                String key = (String) it.next();
                String value = jsonObject.getString(key);
                paramStr += "&" + key + "=" + value;
            }
            return url+paramStr;
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return null;
    }
}
